#include "dialog.h"
#include "ui_dialog.h"

Dialog::Dialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog)
{
    ui->setupUi(this);
    udpSocket=new QUdpSocket(this);
    //创建tcp客户端对象
    tcpSocket = new QTcpSocket(this);//设备建立TCP服务器
    fileSocket=new QTcpSocket(this);//固件升级以及文件传输
    //发送udp广播包
    connect(ui->btnBroadcast,SIGNAL(clicked()),this,SLOT(btnBroadcastSlot()));
    //广播槽函数
    connect(udpSocket,SIGNAL(readyRead()),this,SLOT(udpRecvSlot()));
    //TCP链接
    connect(tcpSocket, SIGNAL(connected()), this, SLOT(onConnected()));
    //询问设备信息
    connect(ui->btnBroadcast_2,SIGNAL(clicked()),this,SLOT(btnBroadcastSlot2()));
    //与设备端通过TCP连接进行通信
    connect(tcpSocket,SIGNAL(readyRead()),this,SLOT(tcpRecvSlot()));
    //再开一路文件传输filesocket传输升级文件
    connect(fileSocket,SIGNAL(connected()),this,SLOT(onConnected2()));
    // connect(fileSocket,SIGNAL(readyRead()),this,SLOT(fileRecvSlot()));

    connect(ui->progressBar,SIGNAL(valueChanged(int)),
            this,SLOT(setValueSlot(int)));
    ui->progressBar->setValue(0);

}

Dialog::~Dialog()
{
    delete ui;
}

void Dialog::btnBroadcastSlot()
{
    QHostAddress broadcastAddress(UDPIP);
    qDebug()<<"\n"<<"UDPIP:"<<UDPIP;
    QByteArray board_Mes1= "message"; // 你想要广播的消息
    if(udpSocket->writeDatagram(board_Mes1,broadcastAddress,8888)==-1)
    {
        qDebug()<<"广播发送失败"<<udpSocket->errorString();
    }
    else
    {
        qDebug()<<"广播发送成功";
        QMessageBox::information(this,"信息","搜索设备完毕");
    }
}

void Dialog::udpRecvSlot()
{

    while (udpSocket->hasPendingDatagrams())
    {
        QByteArray board_Mes2;
        board_Mes2.resize(udpSocket->pendingDatagramSize());
        QHostAddress senderIP;
        quint16 senderPort;
        udpSocket->readDatagram(board_Mes2.data(), board_Mes2.size(), &senderIP, &senderPort);
        TCPIP = senderIP.toString();//获取服务器IP地址

        // 打印发送者地址和接收到的数据
        qDebug() << "Received  from:" << senderIP.toString()<< board_Mes2.data();
        ui->textBrowser_2->append(TCPIP+":"+QString::number(senderPort));
        qDebug()<<board_Mes2.data();
        board_Mes2.toStdString();
        //if(QString(board_Mes2)=="yes")

        if(!strcmp(board_Mes2,"yes"))
        {
            qDebug() << "Device found at:" << TCPIP;
            //currentDeviceIp = TCPIP;
            //emit deviceDiscovered(TCPIP);

            // 自动连接到设备的TCP服务器
            tcpSocket->connectToHost(TCPIP, 8888);
        }

        QJsonObject jsonObj1;
        jsonObj1["type"] = 0;
        jsonObj1["request"] = "connect_info";

        // 将 JSON 对象转换为字符串
        QJsonDocument jsonDoc1(jsonObj1);
        QByteArray jsonString1 = jsonDoc1.toJson(QJsonDocument::Compact);

        // 发送 JSON 字符串
        tcpSocket->write(jsonString1);
        qDebug() << "Request sent";

    }
}

void Dialog::onConnected()
{
    qDebug()<<"TCP Server Connected";
    ui->textBrowser_2->append("TCP Server Connected");
}

void Dialog::btnBroadcastSlot2()
{
    QString filePath("E:\\dest\\gate_away\\Client2\\node.zip");
    if (filePath.isEmpty()) {
        qDebug() << "文件不存在";
        return;
    }
    QFileInfo fileInfo(filePath);
    QFile file(filePath);
    if (!file.open(QIODevice::ReadOnly)) {
        qDebug() << "Cannot open file for reading";
        return;
    }
    // 计算MD5
    QByteArray fileData = file.readAll();
    QByteArray md5 = QCryptographicHash::hash(fileData, QCryptographicHash::Md5).toHex();
    file.close();

    // 创建JSON对象
    QJsonObject jsonObj2;
    jsonObj2["type"] = 1;
    QJsonObject dataObj;
    dataObj["ver"] = "v1.0.1";
    dataObj["file_name"] = fileInfo.fileName();

    //QJsonValue size = QJsonValue::fromVariant(qint64(fileData.size()));//
    dataObj["file_len"] = fileInfo.size();
    dataObj["md5"] =  QString(md5);
    jsonObj2["data"] = dataObj;
    ui->textBrowser_2->append("ver:");



    // 创建JSON文档
    QJsonDocument jsonDoc3(jsonObj2);
    qDebug()<<jsonDoc3.toJson();
    // 将JSON文档转换为字符串
    QByteArray jsonString2 = jsonDoc3.toJson(QJsonDocument::Compact);
    ui->textBrowser_2->append(jsonDoc3.toJson());
    // 发送JSON字符串
    tcpSocket->write(jsonString2);
    qDebug() << "JSON sent:" << jsonDoc3.toJson();
    //  ui->textBrowser_2->append("发送升级请求:" + jsonObj2);




}

//与设备端通过TCP连接进行通信
void Dialog::tcpRecvSlot()
{
    QByteArray receivedData = tcpSocket->readAll(); // 接收到的数据
    QString jsonString0 =receivedData;
    qDebug()<<jsonString0;
   // qDebug()<<receivedData;
    // 使用QJsonDocument解析JSON字符串
    QJsonDocument jsonDoc4 = QJsonDocument::fromJson(jsonString0.toUtf8());
    if (jsonDoc4.isNull()) {
        qDebug() << "Invalid JSON string";
    }
    qDebug()<<jsonDoc4;
    // 将QJsonDocument转换为QJsonObject
    QJsonObject jsonObj3 = jsonDoc4.object();

    // 访问"type"字段
    int type = jsonObj3["type"].toInt();
    QJsonObject dataObj = jsonObj3["data"].toObject();
    //qDebug()<<dataObj;
    qDebug() << "Type:" << type;
    if(type == 0)
    {
        // 访问"data"字段，它是一个JSON对象
        //QJsonObject dataObj = jsonObj3["data"].toObject();

        // 从"data"对象中访问"mqtt_address"和"mqtt_port"字段
        QString mqttAddress = dataObj["mqtt_address"].toString();
        QString mqttPort = dataObj["mqtt_port"].toString();
        ui->textBrowser_2->append("MQTT Address:"+mqttAddress);
        ui->textBrowser_2->append("MQTT Port:"+mqttPort);
        qDebug() << "MQTT Address:" << mqttAddress;
        qDebug() << "MQTT Port:" << mqttPort;
    }
    if(type == 1)
    {
        bool update = dataObj["update"].toBool();
        qDebug() << "type  =" << type;
        qDebug() << "update=" << update;
        if(update==true)
        {
            //fileSocket
            qDebug()<<"开始进行版本升级更新";
            ui->textBrowser_2->append("开始进行版本升级更新");
            qDebug()<<TCPIP;
            fileSocket->connectToHost(TCPIP,8001);
            if (!fileSocket->waitForConnected(1000)) {  // 等待 3 秒
                qDebug() << "File socket connection failed:" << fileSocket->errorString();
            }
        }
        else
        {
            qDebug()<<"不需要进行版本更新";
            ui->textBrowser_2->append("不需要进行版本更新");
        }

    }
    if(type==2)
    {
        bool transSuccess = dataObj["trans_success"].toBool();
        if(transSuccess) {
            qDebug() << "File transfer confirmed successful by device";
            ui->textBrowser_2->append("文件传输成功");
        } else {
            qDebug() << "File transfer failed according to device";
            ui->textBrowser_2->append("文件传输失败");
        }
    }
    if(type==3)
    {
        bool updateSuccess = dataObj["update_success"].toBool();
        if(updateSuccess) {
            qDebug() << "Firmware update confirmed successful by device";
            ui->textBrowser_2->append("固件升级成功");
        } else {
            qDebug() << "Firmware update failed according to device";
            ui->textBrowser_2->append("固件升级失败");
        }
    }


}

void Dialog::onConnected2()
{
    QString filePath("E:\\dest\\gate_away\\Client2\\node.zip");
    qDebug() << "Connected to the device";
    QFile file(filePath);  // 要发送的文件路径
    if (!file.open(QIODevice::ReadOnly)) {
        qDebug() << "Cannot open file for reading";
        return;
    }
    const qint64 chunkSize = 64 * 1024; // 64KB分块
    qint64 totalBytesWritten = 0;
    qint64 fileSize = file.size();




    ui->progressBar->setRange(0, fileSize); // 设置进度条范围
    ui->progressBar->setValue(0);           // 重置进度条
    ui->progressBar->setFormat("%p%");      // 显示百分比

    while (!file.atEnd()) {
        QByteArray chunk = file.read(chunkSize);
        qint64 bytesWritten = fileSocket->write(chunk);

        if (bytesWritten == -1) {
            qDebug() << "发送失败:" << fileSocket->errorString();
            file.close();
            return;
        }

        if (!fileSocket->waitForBytesWritten(3000)) { // 3秒超时
            qDebug() << "写入超时:" << fileSocket->errorString();
            file.close();
            return;
        }

        totalBytesWritten += bytesWritten;
        ui->progressBar->setValue(totalBytesWritten);// 更新进度条
        qDebug() << "已发送:" << totalBytesWritten << "/" << fileSize;

    }
    // Qt端代码（发送文件后）
    fileSocket->disconnectFromHost();  // 发送FIN包

}

